﻿using DevelopTool.Model.CommonModels;
using Sunny.UI;

namespace DevelopTool.Common
{
    using System;

    /// <summary>
    /// TreeView帮助类
    /// </summary>
    using System.Collections;
    using System.Windows.Forms;

    public class TreeViewHelper
    {

        #region 需要初始化使用

        /// <summary>
        /// 存储每个节点的状态（展开或折叠）
        /// </summary>
        private Hashtable storeNodeState = new Hashtable();

        /// <summary>
        /// 将节点的展开状态存入哈希表
        /// </summary>
        /// <param name="fullPath">节点的完整路径</param>
        /// <param name="isExpand">节点的展开状态，null 表示选择并展开</param>
        private void AddNodeStateToHashTable(string fullPath,bool? isExpand)
        {
            if(!storeNodeState.ContainsKey(fullPath))
            {
                storeNodeState.Add(fullPath,isExpand);
            }
        }

        /// <summary>
        /// 清空存储节点状态的哈希表
        /// </summary>
        private void ClearStoreNodeState()
        {
            storeNodeState.Clear();
        }

        /// <summary>
        /// 根据节点完整路径查找节点的展开状态
        /// </summary>
        /// <param name="fullPath">节点的完整路径</param>
        /// <returns>节点的展开状态，true 表示展开，false 表示折叠，null 表示选择并展开</returns>
        private bool? FindNodeStateByFullPath(string fullPath)
        {
            if(storeNodeState.ContainsKey(fullPath))
            {
                return (bool?)storeNodeState[fullPath];
            }
            return false;
        }

        /// <summary>
        /// 在刷新前调用此方法，存储节点的展开状态
        /// </summary>
        /// <param name="treeNode">树节点</param>
        public void ExecStoreNodeState(TreeNode treeNode)
        {
            if(treeNode.Nodes == null || treeNode.Nodes.Count == 0)
                return;

            foreach(TreeNode node in treeNode.Nodes)
            {
                if(node.IsSelected)
                {
                    AddNodeStateToHashTable(node.FullPath,null); // isSelected 并且展开
                    if(node.IsExpanded)
                    {
                        ExecStoreNodeState(node); // 递归存储子节点状态
                        continue;
                    }
                }
                else if(node.IsExpanded)
                {
                    AddNodeStateToHashTable(node.FullPath,true); // 展开状态
                    ExecStoreNodeState(node); // 递归存储子节点状态
                }
                else if(!node.IsExpanded)
                {
                    AddNodeStateToHashTable(node.FullPath,false); // 折叠状态
                    continue;
                }
            }
        }

        /// <summary>
        /// 在刷新后调用此方法，根据存储的状态恢复节点状态
        /// </summary>
        /// <param name="treeNode">树节点</param>
        /// <param name="treeView">TreeView 控件</param>
        public void SetTreeNodeState(TreeNode treeNode,TreeView treeView)
        {
            if(treeNode.Nodes == null || treeNode.Nodes.Count == 0)
                return;

            bool? findFlag = null;
            foreach(TreeNode node in treeNode.Nodes)
            {
                findFlag = FindNodeStateByFullPath(node.FullPath);

                if(findFlag == null)
                {
                    node.ExpandAll(); // 选择并展开节点
                    treeView.SelectedNode = node;
                    continue;
                }
                else if(findFlag == false)
                {
                    node.Collapse(true); // 折叠节点
                    continue;
                }
                else if(findFlag == true)
                {
                    node.Expand(); // 展开节点
                }

                SetTreeNodeState(node,treeView); // 递归设置子节点状态
            }
        }

        /// <summary>
        /// 在刷新后调用此方法，根据存储的状态恢复节点状态（重载方法，适用于 UITreeView）
        /// </summary>
        /// <param name="treeNode">树节点</param>
        /// <param name="treeView">UITreeView 控件</param>
        public void SetTreeNodeState(TreeNode treeNode,UITreeView treeView)
        {
            if(treeNode.Nodes == null || treeNode.Nodes.Count == 0)
                return;

            bool? findFlag = null;
            foreach(TreeNode node in treeNode.Nodes)
            {
                findFlag = FindNodeStateByFullPath(node.FullPath);

                if(findFlag == null)
                {
                    node.ExpandAll(); // 选择并展开节点
                    treeView.SelectedNode = node;
                    continue;
                }
                else if(findFlag == false)
                {
                    node.Collapse(true); // 折叠节点
                    continue;
                }
                else if(findFlag == true)
                {
                    node.Expand(); // 展开节点
                }

                SetTreeNodeState(node,treeView); // 递归设置子节点状态
            }
        }

        #endregion 需要初始化使用


        /// <summary>
        /// 在树节点中查找指定值的节点
        /// </summary>
        /// <param name="tnParent">父节点</param>
        /// <param name="nodeText">节点文本值</param>
        /// <returns>找到的节点，未找到返回 null</returns>
        public static TreeNode FindNode(TreeNode tnParent,string nodeText)
        {
            if(tnParent == null) return null;

            if(tnParent.Text == nodeText) return tnParent;
            else if(tnParent.Nodes.Count == 0) return null;

            TreeNode tnCurrent, tnCurrentPar;
            tnCurrentPar = tnParent;
            tnCurrent = tnCurrentPar.FirstNode;

            while(tnCurrent != null && tnCurrent != tnParent)
            {
                while(tnCurrent != null)
                {
                    if(tnCurrent.Text == nodeText) return tnCurrent;
                    else if(tnCurrent.Nodes.Count > 0)
                    {
                        tnCurrentPar = tnCurrent;
                        tnCurrent = tnCurrent.FirstNode;
                    }
                    else if(tnCurrent != tnCurrentPar.LastNode)
                    {
                        tnCurrent = tnCurrent.NextNode;
                    }
                    else
                        break;
                }

                while(tnCurrent != tnParent && tnCurrent == tnCurrentPar.LastNode)
                {
                    tnCurrent = tnCurrentPar;
                    tnCurrentPar = tnCurrentPar.Parent;
                }

                if(tnCurrent != tnParent)
                    tnCurrent = tnCurrent.NextNode;
            }
            return null;
        }

        /// <summary>
        /// 在树节点中根据 ManageMenu 对象查找节点
        /// </summary>
        /// <param name="tnParent">父节点</param>
        /// <param name="manageMenu">ManageMenu 对象</param>
        /// <returns>找到的节点，未找到返回 null</returns>
        public static TreeNode FindNode(TreeNode tnParent,ManageMenu manageMenu)
        {
            if(tnParent == null || manageMenu == null) return null;

            if(!(tnParent.Tag is ManageMenu tagManageMenu)) return null;

            if(tagManageMenu.Id == manageMenu.Id) return tnParent;
            else if(tnParent.Nodes.Count == 0) return null;

            TreeNode tnCurrent, tnCurrentPar;
            tnCurrentPar = tnParent;
            tnCurrent = tnCurrentPar.FirstNode;

            while(tnCurrent != null && tnCurrent != tnParent)
            {
                while(tnCurrent != null)
                {
                    if(!(tnCurrent.Tag is ManageMenu tagManageMenu2)) continue;

                    if(tagManageMenu2.Id == manageMenu.Id) return tnCurrent;
                    else if(tnCurrent.Nodes.Count > 0)
                    {
                        tnCurrentPar = tnCurrent;
                        tnCurrent = tnCurrent.FirstNode;
                    }
                    else if(tnCurrent != tnCurrentPar.LastNode)
                    {
                        tnCurrent = tnCurrent.NextNode;
                    }
                    else
                        break;
                }

                while(tnCurrent != tnParent && tnCurrent == tnCurrentPar.LastNode)
                {
                    tnCurrent = tnCurrentPar;
                    tnCurrentPar = tnCurrentPar.Parent;
                }

                if(tnCurrent != tnParent)
                    tnCurrent = tnCurrent.NextNode;
            }
            return null;
        }



        /// <summary>
        /// 根据节点名称获取节点对象
        /// </summary>
        /// <param name="treeView">要搜索的 TreeView 对象</param>
        /// <param name="text">节点的名称</param>
        /// <returns>匹配的 TreeNode 对象，如果未找到则返回 null</returns>
        public static TreeNode GetTreeNodeByText(TreeView treeView,string text)
        {
            // 检查输入参数的有效性
            if(treeView == null || string.IsNullOrEmpty(text))
            {
                return null;
            }

            // 调用递归方法查找节点
            return FindNodeByText(text,treeView.Nodes);
        }


        /// <summary>
        /// 递归查找树节点
        /// </summary>
        /// <param name="text">要查找的节点名称</param>
        /// <param name="nodes">要搜索的 TreeNodeCollection 对象</param>
        /// <returns>匹配的 TreeNode 对象，如果未找到则返回 null</returns>
        private static TreeNode FindNodeByText(string text,TreeNodeCollection nodes)
        {
            // 遍历每个节点
            foreach(TreeNode node in nodes)
            {
                // 如果找到匹配的节点
                if(node.Text == text)
                {
                    return node; // 找到目标节点，立即返回
                }

                // 递归查找子节点
                TreeNode foundNode = FindNodeByText(text,node.Nodes);
                if(foundNode != null)
                {
                    return foundNode; // 在子节点中找到目标节点，立即返回
                }
            }

            // 遍历所有节点后仍未找到目标节点
            return null;
        }


        public static int GetMaxImageIndex(TreeView treeView)
        {
            int maxImageIndex = -1;
            foreach (TreeNode node in treeView.Nodes)
            {
                maxImageIndex = Math.Max(maxImageIndex, GetMaxImageIndexRecursive(node));
            }
            return maxImageIndex;
        }

        private static int GetMaxImageIndexRecursive(TreeNode node)
        {
            int maxImageIndex = node.ImageIndex;
            foreach (TreeNode childNode in node.Nodes)
            {
                maxImageIndex = Math.Max(maxImageIndex, GetMaxImageIndexRecursive(childNode));
            }
            return maxImageIndex;
        }
    }

}
